(function($) {

	//closeDOMWindow
	$.fn.closeDOMWindow = function(settings) {

		if (!settings) { settings = {}; }

		var run = function(passingThis) {

			if (settings.anchoredClassName) {
				var $anchorClassName = $('.' + settings.anchoredClassName);
				$anchorClassName.fadeOut('fast', function() {
					if ($.fn.draggable) {
						$anchorClassName.draggable('destory').trigger("unload").remove();
					} else {
						$anchorClassName.trigger("unload").remove();
					}
				});
				if (settings.functionCallOnClose) { settings.functionCallAfterClose(); }
			} else {
				var $DOMWindowOverlay = $('#DOMWindowOverlay');
				var $DOMWindow = $('#DOMWindow');
				$DOMWindowOverlay.fadeOut('fast', function() {
					$DOMWindowOverlay.trigger('unload').unbind().remove();
				});
				$DOMWindow.fadeOut('fast', function() {
					if ($.fn.draggable) {
						$DOMWindow.draggable("destroy").trigger("unload").remove();
					} else {
						$DOMWindow.trigger("unload").remove();
					}
				});

				$(window).unbind('scroll.DOMWindow');
				$(window).unbind('resize.DOMWindow');

				if ($.fn.openDOMWindow.isIE6) { $('#DOMWindowIE6FixIframe').remove(); }
				if (settings.functionCallOnClose) { settings.functionCallAfterClose(); }
			}
		};

		if (settings.eventType) {//if used with $().
			return this.each(function(index) {
				$(this).bind(settings.eventType, function() {
					run(this);
					return false;
				});
			});
		} else {//else called as $.function
			run();
		}

	};

	//allow for public call, pass settings
	$.closeDOMWindow = function(s) { $.fn.closeDOMWindow(s); };

	//openDOMWindow
	$.fn.openDOMWindow = function(instanceSettings) {

		var shortcut = $.fn.openDOMWindow;

		//default settings combined with callerSettings////////////////////////////////////////////////////////////////////////

		shortcut.defaultsSettings = {
			anchoredClassName: '',
			anchoredSelector: '',
			borderColor: '#ccc',
			borderSize: '4',
			draggable: 0,
			eventType: null, //click, blur, change, dblclick, error, focus, load, mousedown, mouseout, mouseup etc...
			fixedWindowY: 100,
			functionCallOnOpen: null,
			functionCallOnClose: null,
			height: 500,
			loader: 0,
			loaderHeight: 0,
			loaderImagePath: '',
			loaderWidth: 0,
			modal: 0,
			overlay: 1,
			overlayColor: '#000',
			overlayOpacity: '85',
			positionLeft: 0,
			positionTop: 0,
			positionType: 'centered', // centered, anchored, absolute, fixed
			width: 500,
			windowBGColor: '#fff',
			windowBGImage: null, // http path
			windowHTTPType: 'get',
			windowPadding: 10,
			windowSource: 'inline', //inline, ajax, iframe
			windowSourceID: '',
			windowSourceURL: '',
			windowSourceAttrURL: 'href'
		};

		var settings = $.extend({}, $.fn.openDOMWindow.defaultsSettings, instanceSettings || {});

		//Public functions

		shortcut.viewPortHeight = function() { return self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; };
		shortcut.viewPortWidth = function() { return self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; };
		shortcut.scrollOffsetHeight = function() { return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; };
		shortcut.scrollOffsetWidth = function() { return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; };
		shortcut.isIE6 = typeof document.body.style.maxHeight === "undefined";

		//Private Functions/////////////////////////////////////////////////////////////////////////////////////////////////////////

		var sizeOverlay = function() {
			var $DOMWindowOverlay = $('#DOMWindowOverlay');
			if (shortcut.isIE6) {//if IE 6
				var overlayViewportHeight = document.documentElement.offsetHeight + document.documentElement.scrollTop - 4;
				var overlayViewportWidth = document.documentElement.offsetWidth - 21;
				$DOMWindowOverlay.css({ 'height': overlayViewportHeight + 'px', 'width': overlayViewportWidth + 'px' });
			} else {//else Firefox, safari, opera, IE 7+
				$DOMWindowOverlay.css({ 'height': '100%', 'width': '100%', 'position': 'fixed' });
			}
		};

		var sizeIE6Iframe = function() {
			var overlayViewportHeight = document.documentElement.offsetHeight + document.documentElement.scrollTop - 4;
			var overlayViewportWidth = document.documentElement.offsetWidth - 21;
			$('#DOMWindowIE6FixIframe').css({ 'height': overlayViewportHeight + 'px', 'width': overlayViewportWidth + 'px' });
		};

		var centerDOMWindow = function() {
			var $DOMWindow = $('#DOMWindow');
			if (settings.height + 50 > shortcut.viewPortHeight()) {//added 50 to be safe
				$DOMWindow.css('left', Math.round(shortcut.viewPortWidth() / 2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindow.outerWidth()) / 2));
			} else {
				$DOMWindow.css('left', Math.round(shortcut.viewPortWidth() / 2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindow.outerWidth()) / 2));
				$DOMWindow.css('top', Math.round(shortcut.viewPortHeight() / 2) + shortcut.scrollOffsetHeight() - Math.round(($DOMWindow.outerHeight()) / 2));
			}
		};

		var centerLoader = function() {
			var $DOMWindowLoader = $('#DOMWindowLoader');
			if (shortcut.isIE6) {//if IE 6
				$DOMWindowLoader.css({ 'left': Math.round(shortcut.viewPortWidth() / 2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindowLoader.innerWidth()) / 2), 'position': 'absolute' });
				$DOMWindowLoader.css({ 'top': Math.round(shortcut.viewPortHeight() / 2) + shortcut.scrollOffsetHeight() - Math.round(($DOMWindowLoader.innerHeight()) / 2), 'position': 'absolute' });
			} else {
				$DOMWindowLoader.css({ 'left': '50%', 'top': '50%', 'position': 'fixed' });
			}

		};

		var fixedDOMWindow = function() {
			var $DOMWindow = $('#DOMWindow');
			$DOMWindow.css('left', settings.positionLeft + shortcut.scrollOffsetWidth());
			$DOMWindow.css('top', +settings.positionTop + shortcut.scrollOffsetHeight());
		};

		var showDOMWindow = function(instance) {
			if (arguments[0]) {
				$('.' + instance + ' #DOMWindowLoader').remove();
				$('.' + instance + ' #DOMWindowContent').fadeIn('fast', function() { if (settings.functionCallOnOpen) { settings.functionCallOnOpen(); } });
				$('.' + instance + '.closeDOMWindow').click(function() {
					$.closeDOMWindow();
					return false;
				});
			} else {
				$('#DOMWindowLoader').remove();
				$('#DOMWindow').fadeIn('fast', function() { if (settings.functionCallOnOpen) { settings.functionCallOnOpen(); } });
				$('#DOMWindow .closeDOMWindow').click(function() {
					$.closeDOMWindow();
					return false;
				});
			}

		};

		var urlQueryToObject = function(s) {
			var query = {};
			s.replace(/b([^&=]*)=([^&=]*)b/g, function(m, a, d) {
				if (typeof query[a] != 'undefined') {
					query[a] += ',' + d;
				} else {
					query[a] = d;
				}
			});
			return query;
		};

		//Run Routine ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
		var run = function(passingThis) {

			//get values from element clicked, or assume its passed as an option
			settings.windowSourceID = $(passingThis).attr('href') || settings.windowSourceID;
			settings.windowSourceURL = $(passingThis).attr(settings.windowSourceAttrURL) || settings.windowSourceURL;
			settings.windowBGImage = settings.windowBGImage ? 'background-image:url(' + settings.windowBGImage + ')' : '';
			var urlOnly, urlQueryObject;

			if (settings.positionType == 'anchored') {//anchored DOM window

				var anchoredPositions = $(settings.anchoredSelector).position();
				var anchoredPositionX = anchoredPositions.left + settings.positionLeft;
				var anchoredPositionY = anchoredPositions.top + settings.positionTop;

				$('body').append('<div class="' + settings.anchoredClassName + '" style="' + settings.windowBGImage + ';background-repeat:no-repeat;padding:' + settings.windowPadding + 'px;overflow:auto;position:absolute;top:' + anchoredPositionY + 'px;left:' + anchoredPositionX + 'px;height:' + settings.height + 'px;width:' + settings.width + 'px;background-color:' + settings.windowBGColor + ';border:' + settings.borderSize + 'px solid ' + settings.borderColor + ';z-index:10001"><div id="DOMWindowContent" style="display:none"></div></div>');
				//loader
				if (settings.loader && settings.loaderImagePath !== '') {
					$('.' + settings.anchoredClassName).append('<div id="DOMWindowLoader" style="width:' + settings.loaderWidth + 'px;height:' + settings.loaderHeight + 'px;"><img src="' + settings.loaderImagePath + '" /></div>');

				}

				if ($.fn.draggable) {
					if (settings.draggable) { $('.' + settings.anchoredClassName).draggable({ cursor: 'move' }); }
				}

				switch (settings.windowSource) {
					case 'inline': //////////////////////////////// inline //////////////////////////////////////////
						$('.' + settings.anchoredClassName + " #DOMWindowContent").append($(settings.windowSourceID).children());
						$('.' + settings.anchoredClassName).unload(function() {// move elements back when you're finished
							$('.' + settings.windowSourceID).append($('.' + settings.anchoredClassName + " #DOMWindowContent").children());
						});
						showDOMWindow(settings.anchoredClassName);
						break;
					case 'iframe': //////////////////////////////// iframe //////////////////////////////////////////
						$('.' + settings.anchoredClassName + " #DOMWindowContent").append('<iframe frameborder="0" hspace="0" wspace="0" src="' + settings.windowSourceURL + '" name="DOMWindowIframe' + Math.round(Math.random() * 1000) + '" style="width:100%;height:100%;border:none;background-color:#fff;" class="' + settings.anchoredClassName + 'Iframe" ></iframe>');
						$('.' + settings.anchoredClassName + 'Iframe').load(showDOMWindow(settings.anchoredClassName));
						break;
					case 'ajax': //////////////////////////////// ajax //////////////////////////////////////////	
						if (settings.windowHTTPType == 'post') {

							if (settings.windowSourceURL.indexOf("?") !== -1) {//has a query string
								urlOnly = settings.windowSourceURL.substr(0, settings.windowSourceURL.indexOf("?"));
								urlQueryObject = urlQueryToObject(settings.windowSourceURL);
							} else {
								urlOnly = settings.windowSourceURL;
								urlQueryObject = {};
							}
							$('.' + settings.anchoredClassName + " #DOMWindowContent").load(urlOnly, urlQueryObject, function() {
								showDOMWindow(settings.anchoredClassName);
							});
						} else {
							if (settings.windowSourceURL.indexOf("?") == -1) { //no query string, so add one
								settings.windowSourceURL += '?';
							}
							$('.' + settings.anchoredClassName + " #DOMWindowContent").load(
								settings.windowSourceURL + '&random=' + (new Date().getTime()), function() {
									showDOMWindow(settings.anchoredClassName);
								});
						}
						break;
				}

			} else {//centered, fixed, absolute DOM window

				//overlay & modal
				if (settings.overlay) {
					$('body').append('<div id="DOMWindowOverlay" style="z-index:10000;display:none;position:absolute;top:0;left:0;background-color:' + settings.overlayColor + ';filter:alpha(opacity=' + settings.overlayOpacity + ');-moz-opacity: 0.' + settings.overlayOpacity + ';opacity: 0.' + settings.overlayOpacity + ';"></div>');
					if (shortcut.isIE6) {//if IE 6
						$('body').append('<iframe id="DOMWindowIE6FixIframe"  src="blank.html"  style="width:100%;height:100%;z-index:9999;position:absolute;top:0;left:0;filter:alpha(opacity=0);"></iframe>');
						sizeIE6Iframe();
					}
					sizeOverlay();
					var $DOMWindowOverlay = $('#DOMWindowOverlay');
					$DOMWindowOverlay.fadeIn('fast');
					if (!settings.modal) { $DOMWindowOverlay.click(function() { $.closeDOMWindow(); }); }
				}

				//loader
				if (settings.loader && settings.loaderImagePath !== '') {
					$('body').append('<div id="DOMWindowLoader" style="z-index:10002;width:' + settings.loaderWidth + 'px;height:' + settings.loaderHeight + 'px;"><img src="' + settings.loaderImagePath + '" /></div>');
					centerLoader();
				}

				//add DOMwindow
				$('body').append('<div id="DOMWindow" style="background-repeat:no-repeat;' + settings.windowBGImage + ';overflow:auto;padding:' + settings.windowPadding + 'px;display:none;height:' + settings.height + 'px;width:' + settings.width + 'px;background-color:' + settings.windowBGColor + ';border:' + settings.borderSize + 'px solid ' + settings.borderColor + '; position:absolute;z-index:10001"></div>');

				var $DOMWindow = $('#DOMWindow');
				//centered, absolute, or fixed
				switch (settings.positionType) {
					case 'centered':
						centerDOMWindow();
						if (settings.height + 50 > shortcut.viewPortHeight()) {//added 50 to be safe
							$DOMWindow.css('top', (settings.fixedWindowY + shortcut.scrollOffsetHeight()) + 'px');
						}
						break;
					case 'absolute':
						$DOMWindow.css({ 'top': (settings.positionTop + shortcut.scrollOffsetHeight()) + 'px', 'left': (settings.positionLeft + shortcut.scrollOffsetWidth()) + 'px' });
						if ($.fn.draggable) {
							if (settings.draggable) { $DOMWindow.draggable({ cursor: 'move' }); }
						}
						break;
					case 'fixed':
						fixedDOMWindow();
						break;
					case 'anchoredSingleWindow':
						var anchoredPositions = $(settings.anchoredSelector).position();
						var anchoredPositionX = anchoredPositions.left + settings.positionLeft;
						var anchoredPositionY = anchoredPositions.top + settings.positionTop;
						$DOMWindow.css({ 'top': anchoredPositionY + 'px', 'left': anchoredPositionX + 'px' });

						break;
				}

				$(window).bind('scroll.DOMWindow', function() {
					if (settings.overlay) { sizeOverlay(); }
					if (shortcut.isIE6) { sizeIE6Iframe(); }
					if (settings.positionType == 'centered') { centerDOMWindow(); }
					if (settings.positionType == 'fixed') { fixedDOMWindow(); }
				});

				$(window).bind('resize.DOMWindow', function() {
					if (shortcut.isIE6) { sizeIE6Iframe(); }
					if (settings.overlay) { sizeOverlay(); }
					if (settings.positionType == 'centered') { centerDOMWindow(); }
				});

				switch (settings.windowSource) {
					case 'inline': //////////////////////////////// inline //////////////////////////////////////////
						$DOMWindow.append($(settings.windowSourceID).children());
						$DOMWindow.unload(function() {// move elements back when you're finished
							$(settings.windowSourceID).append($DOMWindow.children());
						});
						showDOMWindow();
						break;
					case 'iframe': //////////////////////////////// iframe //////////////////////////////////////////
						$DOMWindow.append('<iframe frameborder="0" hspace="0" wspace="0" src="' + settings.windowSourceURL + '" name="DOMWindowIframe' + Math.round(Math.random() * 1000) + '" style="width:100%;height:100%;border:none;background-color:#fff;" id="DOMWindowIframe" ></iframe>');
						$('#DOMWindowIframe').load(showDOMWindow());
						break;
					case 'ajax': //////////////////////////////// ajax //////////////////////////////////////////
						if (settings.windowHTTPType == 'post') {

							if (settings.windowSourceURL.indexOf("?") !== -1) {//has a query string
								urlOnly = settings.windowSourceURL.substr(0, settings.windowSourceURL.indexOf("?"));
								urlQueryObject = urlQueryToObject(settings.windowSourceURL);
							} else {
								urlOnly = settings.windowSourceURL;
								urlQueryObject = {};
							}
							$DOMWindow.load(urlOnly, urlQueryObject, function() {
								showDOMWindow();
							});
						} else {
							if (settings.windowSourceURL.indexOf("?") == -1) { //no query string, so add one
								settings.windowSourceURL += '?';
							}
							$DOMWindow.load(
								settings.windowSourceURL + '&random=' + (new Date().getTime()), function() {
									showDOMWindow();
								});
						}
						break;
				}

			} //end if anchored, or absolute, fixed, centered

		}; //end run()

		if (settings.eventType) {//if used with $().
			return this.each(function(index) {
				$(this).bind(settings.eventType, function() {
					run(this);
					return false;
				});
			});
		} else {//else called as $.function
			run();
		}

	}; //end function openDOMWindow

	//allow for public call, pass settings
	$.openDOMWindow = function(s) { $.fn.openDOMWindow(s); };

})(jQuery);
